package com.stylefeng.guns.modular.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.config.redis.RedisUtil;
import com.stylefeng.guns.modular.small.Enums.OrderApiEnum;
import com.stylefeng.guns.modular.small.dao.BizConsumerMapper;
import com.stylefeng.guns.modular.small.dto.*;
import com.stylefeng.guns.modular.small.model.BizConsumer;
import com.stylefeng.guns.modular.small.util.*;
import com.stylefeng.guns.modular.system.dao.ArtificerBusinessMapper;
import com.stylefeng.guns.modular.system.dao.ConsumerOrderMapper;
import com.stylefeng.guns.modular.system.dao.CustomerAddressMapper;
import com.stylefeng.guns.modular.system.dto.ConsumerOrderDTO;
import com.stylefeng.guns.modular.system.model.ArtificerBusiness;
import com.stylefeng.guns.modular.system.model.ConsumerOrder;
import com.stylefeng.guns.modular.system.model.CustomerAddress;
import com.stylefeng.guns.modular.system.service.IConsumerOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单记录表 服务实现类
 * </p>
 *
 * @author stylefeng
 * @since 2019-09-09
 */
@Service
@Slf4j
public class ConsumerOrderServiceImpl extends ServiceImpl<ConsumerOrderMapper, ConsumerOrder> implements IConsumerOrderService {

    @Resource
    private ArtificerBusinessMapper artificerBusinessMapper;

    @Resource
    private ConsumerOrderMapper consumerOrderMapper;

    @Resource
    private BizConsumerMapper bizConsumerMapper;

    @Resource
    private CustomerAddressMapper customerAddressMapper;

    private static String TRADE_TYPE = "JSAPI";

    private static String TEST_OPENID = "oHZqt5k32ZiUWZaCc5UBsHFspBgs";

    @Resource
    private RedisUtil redisUtil;

    @Value("${wx.appid}")
    private String APPID;

    @Value("${wx.mch_id}")
    private String MCH_ID;

    /***
     *  JSAPI支付
     * @param request
     * @param orderParamDTO
     *{
     *     "data": {
     *         "nonce_str": "LdaJJ3eRxoFgZy6w",
     *         "appid": "wx224e8b702efc0e2b",
     *         "sign": "A4048140736FBAD74F334115493EF268",
     *         "trade_type": "JSAPI",
     *         "return_msg": "OK",
     *         "result_code": "SUCCESS",
     *         "mch_id": "1539993251",
     *         "return_code": "SUCCESS",
     *         "prepay_id": "wx21212423925507e560aefb1d1075121900"
     *     },
     *     "msg": "OK",
     *     "status": "0000",
     *     "userType": ""
     * }
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResultDTO createOrder(HttpServletRequest request, OrderParamDTO orderParamDTO) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        if(orderParamDTO.getConsumerId()==null){
            resultDTO.setStatus("-1");
            resultDTO.setMsg("PARAM IS NULL!");
            return resultDTO;
        }
        BizConsumer bizConsumer= bizConsumerMapper.selectById(orderParamDTO.getConsumerId());
        if(bizConsumer==null){
            resultDTO.setStatus("-1");
            resultDTO.setMsg("消费者不存在!");
            return resultDTO;
        }
        if(orderParamDTO.getAddressId()==null){
            resultDTO.setStatus("-1");
            resultDTO.setMsg("收货地址不能为空!");
            return resultDTO;
        }
        //先判断接收参数的产品类型，查到产品金额必须和查到的产品类型的金额一样
        if (orderParamDTO != null && orderParamDTO.getTotalFee() == null) {
            resultDTO.setStatus("-1");
            resultDTO.setMsg("支付金额缺少!");
            return resultDTO;
        }
        if (orderParamDTO != null && orderParamDTO.getBusinessType() != null) {
            ArtificerBusiness artificerBusiness = artificerBusinessMapper.selectById(orderParamDTO.getBusinessType());
            if (artificerBusiness != null && !orderParamDTO.getTotalFee().equals(artificerBusiness.getPrice())) {
                resultDTO.setStatus("-1");
                resultDTO.setMsg("支付金额与产品金额不匹配!");
                return resultDTO;
            }
        }
        InputStream in = null;
        try {
            String orderNo = GeneratorOrderNoUtil.GeneratorOrderNo();
            log.info("生成的订单号位：{}", orderNo);
            orderParamDTO.setOrderNo(orderNo);
            //数据库创建订单
            resultDTO =  saveOrder(orderParamDTO);
            if("-1".equals(resultDTO.getStatus()))
                return resultDTO;
            RequestDTO requestDTO = new RequestDTO();
            requestDTO.setAppid(APPID);
            requestDTO.setAttach("测试支付回调返回,订单号: ".concat(orderNo));
            requestDTO.setBody("298全身精油推背");
            requestDTO.setMch_id(MCH_ID);
            requestDTO.setDetail(JSONObject.toJSONString(orderParamDTO));
            requestDTO.setNonce_str(String.valueOf(System.currentTimeMillis()));
            requestDTO.setNotify_url(OrderApiEnum.CALL_BACK_URL.getValue());
            requestDTO.setOpenid(bizConsumer.getOpenId());
            requestDTO.setOut_trade_no(orderNo);
            requestDTO.setSpbill_create_ip(request.getRemoteAddr());
            requestDTO.setTotal_fee((orderParamDTO.getTotalFee() + orderParamDTO.getDeliveryFee()));
            requestDTO.setTrade_type(TRADE_TYPE);
            String sign = SignUtil.getSign(requestDTO, redisUtil.get("API_KEY").toString());
            requestDTO.setSign(sign);
            String xmlParam = ObjectToXml.ObjecttoXML(requestDTO).replaceAll("object", "xml");
            log.info("===============>请求参数转为XML：{}", xmlParam);
            CloseableHttpClient httpClient = HttpConnectionManager.getHttpClient();
            HttpPost post = new HttpPost(OrderApiEnum.UNIFIED_ORDER_URL.getValue());
            // 构建消息实体
            StringEntity entity = new StringEntity(xmlParam, Charset.forName("UTF-8"));
            // 发送Json格式的数据请求
            entity.setContentType("text/xml; charset=utf-8");
            post.setEntity(entity);

            CloseableHttpResponse response = httpClient.execute(post);
            in = response.getEntity().getContent();
            String responseString = IOUtils.toString(in);
            Map resultMap = ObjectToXml.xmlToMap(responseString);
            resultDTO.setMsg(MapUtils.getString(resultMap, "return_msg"));
            resultDTO.setStatus("FAIL".equals(MapUtils.getString(resultMap, "return_code")) ? "-1" : "0000");
            if ("OK".equals(MapUtils.getString(resultMap, "return_msg")) && "SUCCESS".equals(MapUtils.getString(resultMap, "return_code"))) {
                SignDTO signDTO = new SignDTO();
                signDTO.setAppId(MapUtils.getString(resultMap, "appid"));
                signDTO.setNonceStr(String.valueOf(System.currentTimeMillis()));
                signDTO.setTimeStamp(String.valueOf(System.currentTimeMillis()));
                signDTO.setPackages("prepay_id=".concat(MapUtils.getString(resultMap, "prepay_id")));
                String sign2 = SignUtil.getSign(signDTO, redisUtil.get("API_KEY").toString());
                signDTO.setPaySign(sign2);
                resultDTO.setData(signDTO);
            }
            log.info("响应返回的信息:{}", responseString);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("创建订单异常,异常信息为:{}", e.getMessage());
            resultDTO.setMsg("创建订单异常!");
            resultDTO.setStatus("-1");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException c) {
                    c.printStackTrace();
                    log.info("关闭流异常，异常信息为:{}", c.getMessage());
                }
            }
        }
        return resultDTO;
    }

    @Override
    public ResponseResultDTO orderqueryAndUpdateOrder(HttpServletRequest request, String attach) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        try {

        } catch (Exception e) {
            e.printStackTrace();
            log.info("系统异常orderqueryAndUpdateOrder：{}", e.getMessage());
            resultDTO.setMsg("更新订单异常!");
            resultDTO.setStatus("-1");
        }
        return resultDTO;
    }

    @Override
    public ResponseResultDTO queryOrder(String orderNo) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        InputStream in = null;
        try {
            QueryOrderDTO orderDTO = new QueryOrderDTO();
            orderDTO.setAppid(APPID);
            orderDTO.setMch_id(MCH_ID);
            orderDTO.setOut_trade_no(orderNo);
            orderDTO.setNonce_str(String.valueOf(System.currentTimeMillis()));
            String sign = SignUtil.getSign(orderDTO, redisUtil.get("API_KEY").toString());
            orderDTO.setSign(sign);
            String xmlParam = ObjectToXml.ObjecttoXML(orderDTO).replaceAll("object", "xml");
            log.info("===============>请求参数转为XML：{}", xmlParam);
            CloseableHttpClient httpClient = HttpConnectionManager.getHttpClient();
            HttpPost post = new HttpPost(OrderApiEnum.ORDER_QUERY_URL.getValue());
            // 构建消息实体
            StringEntity entity = new StringEntity(xmlParam, Charset.forName("UTF-8"));
            // 发送Json格式的数据请求
            entity.setContentType("text/xml; charset=utf-8");
            post.setEntity(entity);

            CloseableHttpResponse response = httpClient.execute(post);
            in = response.getEntity().getContent();
            String responseString = IOUtils.toString(in);
            log.info("查询订单接口响应结果为:{}",responseString);
            resultDTO.setData(responseString);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("查询订单接口异常：{}", e.getMessage());
            resultDTO.setMsg("更新订单异常!");
            resultDTO.setStatus("-1");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException c) {
                    c.printStackTrace();
                    log.info("关闭流异常，异常信息为:{}", c.getMessage());
                }
            }
        }
        return resultDTO;
    }

    @Override
    public ResponseResultDTO refund(String orderNo) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        if (StringUtils.isBlank(orderNo)) {
            resultDTO.setMsg("ORDERNO-NULL");
            resultDTO.setStatus("-1");
            return resultDTO;
        }
        InputStream in = null;
        try {
            ConsumerOrder  param=new ConsumerOrder();
            param.setOrderNo(orderNo);
            ConsumerOrder consumerOrder= consumerOrderMapper.selectOne(param);
            if(consumerOrder==null){
                resultDTO.setMsg("该笔订单不存在");
                resultDTO.setStatus("-1");
                return resultDTO;
            }
            RefundOrderDTO refundOrderDTO = new RefundOrderDTO();
            refundOrderDTO.setAppid(APPID);
            refundOrderDTO.setMch_id(MCH_ID);
            refundOrderDTO.setNonce_str(String.valueOf(System.currentTimeMillis()));
            refundOrderDTO.setOut_refund_no(orderNo);
            refundOrderDTO.setOut_trade_no(orderNo);
            refundOrderDTO.setRefund_fee(consumerOrder.getSubscribeMoney());
            refundOrderDTO.setTotal_fee(consumerOrder.getSubscribeMoney());
            String sign = SignUtil.getSign(refundOrderDTO, redisUtil.get("API_KEY").toString());
            refundOrderDTO.setSign(sign);
            String xmlParam = ObjectToXml.ObjecttoXML(refundOrderDTO).replaceAll("object", "xml");
            log.info("===============>请求参数转为XML：{}", xmlParam);
            CloseableHttpClient httpClient = HttpConnectionManager.getHttpClient();
            HttpPost post = new HttpPost(OrderApiEnum.ORDER_QUERY_URL.getValue());
            // 构建消息实体
            StringEntity entity = new StringEntity(xmlParam, Charset.forName("UTF-8"));
            // 发送Json格式的数据请求
            entity.setContentType("text/xml; charset=utf-8");
            post.setEntity(entity);

            CloseableHttpResponse response = httpClient.execute(post);
            in = response.getEntity().getContent();
            String responseString = IOUtils.toString(in);
            Map resultMap = ObjectToXml.xmlToMap(responseString);
            log.info("退单接口响应结果为:{}",resultMap);
            resultDTO.setData(resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("退单异常：{}", e.getMessage());
            resultDTO.setMsg("退单异常!");
            resultDTO.setStatus("-1");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException c) {
                    c.printStackTrace();
                    log.info("关闭流异常，异常信息为:{}", c.getMessage());
                }
            }
        }
        return resultDTO;
    }

    @Override
    public ResponseResultDTO refundQuery(String orderNo) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        try{

        }catch (Exception e){
            e.printStackTrace();

        }
        return resultDTO;
    }

    /**
     * 创建订单
     *
     * @param orderParamDTO
     */
    private ResponseResultDTO saveOrder(OrderParamDTO orderParamDTO) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        CustomerAddress customerAddress= customerAddressMapper.selectById(orderParamDTO.getAddressId());
        if(customerAddress==null){
            resultDTO.setStatus("-1");
            resultDTO.setMsg("没有查询到该用户地址的存在!");
            return resultDTO;
        }
        ConsumerOrder consumerOrder = new ConsumerOrder();
        consumerOrder.setCreateTime(new Date());
        consumerOrder.setStatus(0);
        consumerOrder.setSubscribeMoney(orderParamDTO.getTotalFee());
        consumerOrder.setAddressId(orderParamDTO.getAddressId());
        consumerOrder.setRemark(orderParamDTO.getRemark());
        consumerOrder.setReserveType(orderParamDTO.getBusinessType());
        consumerOrder.setArtificerId(orderParamDTO.getArtificerId());
        consumerOrder.setConsumerId(orderParamDTO.getConsumerId());
        consumerOrder.setSubscribeTime(new Date(orderParamDTO.getAppointmentTime()));
        consumerOrder.setPullCount(0);
        consumerOrder.setName(customerAddress.getName());
        consumerOrder.setAddress(customerAddress.getAddress());
        consumerOrder.setPhone(customerAddress.getPhone());
        consumerOrder.setOrderNo(orderParamDTO.getOrderNo());
        consumerOrderMapper.insert(consumerOrder);
        return  resultDTO;
    }

    @Override
    public ResponseResultDTO searchOrder(ConsumerOrderDTO param) {
        ResponseResultDTO resultDTO = new ResponseResultDTO();
        try {
            List<ConsumerOrder> list = consumerOrderMapper.selectOrder(param);
            resultDTO.setData(list);
        } catch (Exception e) {
            e.printStackTrace();
            resultDTO.setMsg("系统异常");
            resultDTO.setStatus("-1");
        }
        return resultDTO;
    }
}
